#include "iConfig.hpp"

#if GLF_ENABLE_DEBUGGER

#include <glf/core/timer.h>
#include <glf/debugger/console.h>
#include <glf/debugger/network.h>

namespace glf
{
namespace debugger
{
	Console::Console() :
		Module("CONSOLE")
	{
		
	}

	GLF_DEFINE_SINGLETON_WITH_DEP(Console, Debugger)
	
	Console::~Console()
	{
        if( glf::debugger::Debugger::GetInstance() )
        {
		    glf::debugger::Debugger::GetInstance()->UnregisterModule( this );
        }
	}

	void Console::Print(const char* str, const char* consoleID, uint color)
	{
		if(!Debugger::GetInstance()->IsConnected())
			return;

		ScopeMutex mutex;
		if(str != NULL)
		{
			Console::GetInstance()->mPendingLogs.push_back(Entry(str, consoleID, color, GetMicroseconds()));

			Network::Event e(Network::EVENT_LOG, 0, str);
			Network::AddEvent(e);
		}
		else
		{
			Console::GetInstance()->SendLogs();
		}
	}

	void Console::VPrintf(const char* consoleID, uint color, const char* fmt, glfVaList argp)
	{
		if(!Debugger::GetInstance()->IsConnected())
			return;

		ScopeMutex mutex;
		if(fmt != NULL)
		{
			char buffer[1024];
			glf::Vsnprintf(buffer, sizeof(buffer), fmt, argp);
			
			GLF_ASSERT(strlen(buffer) < sizeof(buffer));
			Console::GetInstance()->mPendingLogs.push_back(Entry(buffer, consoleID, color, GetMicroseconds()));

			Network::Event e(Network::EVENT_LOG, 0, buffer);
			Network::AddEvent(e);
		}
		else
		{
			Console::GetInstance()->SendLogs();
		}
	}

	void Console::VPrintf(const char* consoleID, const char* fmt, glfVaList argp)
	{
		VPrintf(consoleID, BLACK, fmt, argp);
	}

	void Console::VPrintf(const char* fmt, glfVaList argp)
	{
		VPrintf("", BLACK, fmt, argp);
	}

	void Console::Printf(const char* consoleID, uint color, const char* fmt, ...)
	{
		glfVaList argp;
		va_start(argp, fmt);
		VPrintf(consoleID, color, fmt, argp);
		va_end(argp);
	}

	void Console::Printf(const char* consoleID, const char* fmt, ...)
	{
		glfVaList argp;
		va_start(argp, fmt);
		VPrintf(consoleID, fmt, argp);
		va_end(argp);
	}

	void Console::Printf(const char* fmt, ...)
	{
		glfVaList argp;
		va_start(argp, fmt);
		VPrintf(fmt, argp);
		va_end(argp);
	}

	void Console::Clear(const char* consoleID)
	{
		if(!Debugger::GetInstance()->IsConnected())
			return;

		ScopeMutex mutex;
		Console::GetInstance()->mPendingLogs.push_back(Entry("", consoleID, 0x0, 0));
	}

	void Console::UpdateFrame()
	{
		SendLogs();
	}

	void Console::SendLogs()
	{
		if(!Debugger::GetInstance()->IsConnected())
			return;

		ScopeMutex mutex;
		if(mPendingLogs.size() > 0)
		{
			// flush logs in single packet
			PacketWriter& pw = GetPacketWriter();
			pw.Init(MESSAGE_LOGS);
			pw.Write((uint)mPendingLogs.size());
			
			for(uint i = 0; i < mPendingLogs.size(); i++)
			{
				pw.Write(mPendingLogs[i].mStr.c_str());
				pw.Write(mPendingLogs[i].mConsoleID.c_str());
				pw.Write(mPendingLogs[i].mColor);
				pw.Write(mPendingLogs[i].mTimeStamp);
			}
			
			Send(pw);
			mPendingLogs.clear();
		}
	}

} //namespace debugger
} //namespace glf

#endif // GLF_ENABLE_DEBUGGER
